home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / PATCH10 < prev    next >
Text File  |  1989-12-31  |  46KB  |  1,791 lines

  1. This is patch 10 for nn release 6.3
  2.  
  3. This is primarily a "new features" release, but it also fixes some
  4. bugs (low priority ones).
  5.  
  6.  
  7. BUGS FIXED
  8. ----------
  9.  
  10. The tables in the online manual are now properly aligned.
  11.  
  12. A core dump when viewing empty articles have been fixed (thanks to
  13. Sjoerd Mullender).
  14.  
  15. Type-ahead will now be flushed when entering a new group (since you
  16. don't know which group it is, nor which articles are in it, what would
  17. you type-ahead anyway?)
  18.  
  19. Number of killed articles on the menu is now updated when you kill
  20. articles with the K command.
  21.  
  22. The `Y' {overview} command now marks groups with an entry macro with a
  23. % after the name.
  24.  
  25. The entry macro is no longer executed again after a goto-group command
  26. completes.  You can now use local variables described below instead.
  27.  
  28. The nncheck -t output format is now similar to the output from the `Y'
  29. command (but only one column).
  30.  
  31. Specifying `comp.' in the presentation sequence no longer (falsely)
  32. includes `comp' (bad example, since there is no comp group, but I hope
  33. you get the idea).
  34.  
  35. Variable name completion now works for no"name.." also.
  36.  
  37.  
  38. NEW FEATURES
  39. ------------
  40.  
  41. The variables can now be assigned local values which are only
  42. effective until the current group is left.  A variable is made local
  43. using the :local command, e.g.
  44.  
  45.     :local cross-post
  46.  
  47. A new value can be assigned to the local variable in the same command:
  48.  
  49.     :local cross-post on
  50.     :local auto-preview-mode off
  51.     :local default-save-file +src/$L/misc
  52.  
  53. Local variables are marked with a '>' in front of the name when
  54. displayed with the :set command.
  55.  
  56. This can be combined with a new "on group groups..." construction:
  57.  
  58.     on group comp.sources* alt.sources
  59.         :local kill off
  60.     end
  61.  
  62. This allows you to specify entry macros for several groups without
  63. disrupting the presentation sequence.
  64.  
  65.  
  66. $(VAR) can now be specified in file names - it is expanded into the
  67. value of the environment variable VAR.  For example, you can specify
  68. this in the global init file (provided every user has a MAIL variable
  69. set): 
  70.     set mail $(MAIL)
  71.  
  72.  
  73. There is a new "Auto Preview Mode" where hitting the article id letter
  74. immediately enters preview mode rather than selecting the article.  It
  75. is enabled by setting the auto-preview-mode variable.
  76.  
  77.  
  78. There are new options to nnmaster:
  79.     -B    Remove bad articles from the spool directory
  80.     -b    Do not ignore bad articles.
  81.     -Ltypes    Do not write entries of the specified types in the log file.
  82.  
  83. There is a new confirm-create variable that will cause nn to wait for
  84. confirmation before creating new files.
  85.  
  86. TO APPLY:
  87.  
  88. Feed this patch through the "patch" program.
  89.  
  90.  
  91. *** /usr/storm/nn6.3.9/patchlevel.h    Fri Oct 20 23:24:42 1989
  92. --- patchlevel.h    Thu Oct 26 12:46:09 1989
  93. ***************
  94. *** 29,35 ****
  95.    *
  96.    *    1989-09-15:  Patch 8: pack_name.c nntp.c
  97.    *    1989-10-20:  Patch 9: several files
  98.    */
  99.   
  100. ! #define PATCHLEVEL 9
  101.   
  102. --- 29,36 ----
  103.    *
  104.    *    1989-09-15:  Patch 8: pack_name.c nntp.c
  105.    *    1989-10-20:  Patch 9: several files
  106. +  *    1989-11-17:  Patch 10: several files
  107.    */
  108.   
  109. ! #define PATCHLEVEL 10
  110.   
  111.  
  112. *** /usr/storm/nn6.3.9/answer.c    Fri Oct 20 23:24:44 1989
  113. --- answer.c    Thu Nov 16 15:39:21 1989
  114. ***************
  115. *** 281,287 ****
  116.           return 2;
  117.       }
  118.       } else {
  119. !     prompt("Confirm cancel: '%.50s'", ah->subject ? ah->subject : ""); 
  120.       if (yes(1) <= 0) return 1;
  121.       }
  122.       
  123. --- 281,289 ----
  124.           return 2;
  125.       }
  126.       } else {
  127. !     prompt("Confirm cancel: '%s: %.30s'",
  128. !            ah->sender ? ah->sender : "",
  129. !            ah->subject ? ah->subject : ""); 
  130.       if (yes(1) <= 0) return 1;
  131.       }
  132.       
  133.  
  134. *** /usr/storm/nn6.3.7/articles.h    Fri Sep  8 12:46:41 1989
  135. --- articles.h    Tue Oct 24 10:11:54 1989
  136. ***************
  137. *** 7,15 ****
  138.   article_number    n_articles;
  139.   article_header     **articles;
  140.   
  141. - /* number of articles killed by last access_group call */
  142. - int         killed_articles;
  143.   
  144.   typedef struct thunk {
  145.       char      *this_thunk;
  146. --- 7,12 ----
  147.  
  148. *** /usr/storm/nn6.3.7/collect.c    Fri Sep  8 12:46:41 1989
  149. --- collect.c    Tue Oct 31 18:27:59 1989
  150. ***************
  151. *** 4,9 ****
  152. --- 4,12 ----
  153.   
  154.   #define COUNT_RE_REFERENCES    /* no of >>> depends on Reference: line */
  155.   
  156. + export int ignore_bad_articles = 1;    /* no Newsgroups: line */
  157. + export int remove_bad_articles = 0;
  158.   import int trace;
  159.   
  160.   
  161. ***************
  162. *** 128,134 ****
  163.        * it is not really necessary to save anything in the data file
  164.        * we simply use the index file to get the *first* available article
  165.        */
  166. !     return 1;    /* but we have still collected one article */
  167.       }
  168.   
  169.       /* map cross-postings into a list of group numbers */
  170. --- 131,151 ----
  171.        * it is not really necessary to save anything in the data file
  172.        * we simply use the index file to get the *first* available article
  173.        */
  174. !     return 0;
  175. !     }
  176. !     if (ignore_bad_articles && news.ng_groups == NULL) {
  177. !     char *rem = "";
  178. !     
  179. ! #ifndef NNTP
  180. !     if (remove_bad_articles) {
  181. !         unlink(group_path_name);
  182. !         rem = "removed ";
  183. !     }
  184. ! #endif NNTP
  185. !     log_entry('B', "%sbad article: %s/%ld", rem, 
  186. !           current_group->group_name, (long)art_num);
  187. !     return 0;
  188.       }
  189.   
  190.       /* map cross-postings into a list of group numbers */
  191.  
  192. *** /usr/storm/nn6.3.9/folder.c    Fri Oct 20 23:24:47 1989
  193. --- folder.c    Fri Nov 17 18:51:47 1989
  194. ***************
  195. *** 65,70 ****
  196. --- 65,86 ----
  197.           
  198.       }
  199.   
  200. +     if (c == '$' && src[1] == '(') {
  201. +         char envar[64];
  202. +         for (src += 2, cp = envar; (c = *src) != NUL && c != ')'; src++) 
  203. +         *cp++ = c;
  204. +         *cp = NUL;
  205. +         if (cp != envar) {
  206. +         if ((cp = getenv(envar)) != NULL)
  207. +             while (*cp) *dp++ = *cp++;
  208. +         else {
  209. +             msg("Environment variable $(%d) not set", envar);
  210. +             return 0;
  211. +         }
  212. +         }
  213. +         goto no_parse;
  214. +     }
  215. +         
  216.       if (c == '$' && !isalnum(src[2])) {
  217.           remap = 0;
  218.           cp = NULL;
  219.  
  220. *** /usr/storm/nn6.3.9/global.c    Fri Oct 20 23:24:47 1989
  221. --- global.c    Fri Nov  3 08:45:11 1989
  222. ***************
  223. *** 8,13 ****
  224. --- 8,14 ----
  225.   export char news_directory[] = NEWS_DIRECTORY;    /* /usr/spool/news */
  226.   export char lib_directory[]  = LIB_DIRECTORY;    /* /usr/local/lib/nn     */
  227.   export char db_directory[]   = DB_DIRECTORY;    /* /usr/spool/nn    */
  228. + export char *log_entry_filter = NULL;
  229.   
  230.   export char *temp_file;
  231.   
  232. ***************
  233. *** 479,484 ****
  234. --- 480,489 ----
  235.   {
  236.       FILE *log;
  237.       char *msg, buf[512], logname[512];
  238. +     if (log_entry_filter != NULL)
  239. +     for (msg = log_entry_filter; *msg; msg++)
  240. +         if (*msg == type) return 1;
  241.   
  242.       msg  = va_arg1(char *);
  243.       vsprintf(buf, msg, va_args2toN);
  244.  
  245. *** /usr/storm/nn6.3.7/group.c    Fri Sep  8 12:46:43 1989
  246. --- group.c    Tue Oct 24 10:11:54 1989
  247. ***************
  248. *** 21,26 ****
  249. --- 21,27 ----
  250.   import int  article_limit, also_read_articles;
  251.   import int  no_update;
  252.   import int  merged_menu;
  253. + import int  killed_articles;
  254.   
  255.   char *quick_match();
  256.   
  257. ***************
  258. *** 277,283 ****
  259.       if ((subpattern && !regexec(subpattern, ah->subject)) ||
  260.       (submask && quick_match(ah->subject, submask) == NULL) ||
  261.       (do_kill && kill_article(ah))) {
  262. -     killed_articles++;
  263.       release_str(&str_marker);
  264.       goto read_next;
  265.       }
  266. --- 278,283 ----
  267. ***************
  268. *** 371,377 ****
  269.       o_first_article = current_first_article;
  270.       o_killed = killed_articles;
  271.       mark_memory(&sel_marker);
  272.       if (init_group(gh) <= 0) menu_return( ME_NEXT );
  273.       m_invoke(-1);
  274.       
  275. --- 371,378 ----
  276.       o_first_article = current_first_article;
  277.       o_killed = killed_articles;
  278.       mark_memory(&sel_marker);
  279. !     mark_var_stack();
  280. !     
  281.       if (init_group(gh) <= 0) menu_return( ME_NEXT );
  282.       m_invoke(-1);
  283.       
  284. ***************
  285. *** 513,518 ****
  286. --- 514,520 ----
  287.       
  288.       current_first_article = o_first_article;
  289.       killed_articles = o_killed;
  290. +     restore_variables();
  291.       
  292.       return menu_cmd;
  293.   }
  294. ***************
  295. *** 844,850 ****
  296.   
  297.       if (gh != orig_group) {
  298.       current_first_article = o_current_first;
  299. !     if (orig_group) { init_group(orig_group); m_invoke(-1); }
  300.       }
  301.       
  302.   goto_exit:
  303. --- 846,852 ----
  304.   
  305.       if (gh != orig_group) {
  306.       current_first_article = o_current_first;
  307. !     if (orig_group) init_group(orig_group);
  308.       }
  309.       
  310.   goto_exit:
  311. ***************
  312. *** 993,999 ****
  313.          (long)(gh->last_l_article - gh->last_article),
  314.          (gh == current_group) ? '*' : ' ',
  315.          gh->group_name,
  316. !        gh->group_flag & G_SUBSCRIPTION ? "" : " (!)");
  317.   
  318.       return 0;
  319.   }
  320. --- 995,1002 ----
  321.          (long)(gh->last_l_article - gh->last_article),
  322.          (gh == current_group) ? '*' : ' ',
  323.          gh->group_name,
  324. !        (gh->group_flag & G_SUBSCRIPTION) == 0 ? " (!)" :
  325. !        gh->enter_macro ? " %" : "");
  326.   
  327.       return 0;
  328.   }
  329.  
  330. *** /usr/storm/nn6.3.9/init.c    Fri Oct 20 23:24:49 1989
  331. --- init.c    Fri Nov  3 16:01:39 1989
  332. ***************
  333. *** 212,217 ****
  334. --- 212,218 ----
  335.       "decode",            6,    0,
  336.       "define",            6,    0,
  337.       "help",            4,    2,
  338. +     "local",            5,    3,
  339.       "man",            3,    0,
  340.       "map",            3,    -1,
  341.       "map both",            8,    4,
  342. ***************
  343. *** 219,224 ****
  344. --- 220,226 ----
  345.       "map menu",            8,    4,
  346.       "map show",            8,    4,
  347.       "mkdir",            5,    1,
  348. +     "patch",            5,    0, /* QUICK HACK */
  349.       "print",            5,    0, /* QUICK HACK */
  350.       "pwd",            3,    0,
  351.       "rmail",            5,    0,
  352. ***************
  353. *** 403,408 ****
  354. --- 405,411 ----
  355.   FILE *initf;
  356.   {
  357.       extern char *m_define(), *parse_enter_macro();
  358. +     int i;
  359.       
  360.       if (!split_command(cmd)) return ok_val;
  361.   
  362. ***************
  363. *** 427,432 ****
  364. --- 430,447 ----
  365.           return ok_val;
  366.       }
  367.       
  368. +     CASE( "local" ) {
  369. +         if (ARGTAIL == NULL) goto stx_err;
  370. +         
  371. +         cmd = argv(1);
  372. +         if (!push_variable(cmd)) return ok_val;
  373. +         
  374. +         if (ARGTAIL && set_variable(cmd, 1, ARGTAIL))
  375. +         return AC_REDRAW;
  376. +         else
  377. +         return ok_val;
  378. +     }
  379. +         
  380.       CASE( "set" ) {
  381.           if (ARGTAIL == NULL) {
  382.           disp_variables();
  383. ***************
  384. *** 856,862 ****
  385.           
  386.           if (code != K_INVALID) {
  387.           menu_key_map[parse_key(argv(2))] = code;
  388. !         return;
  389.           }
  390.       }
  391.       
  392. --- 871,877 ----
  393.           
  394.           if (code != K_INVALID) {
  395.           menu_key_map[parse_key(argv(2))] = code;
  396. !         if (!map_show) return;
  397.           }
  398.       }
  399.       
  400. ***************
  401. *** 910,917 ****
  402.       
  403.       CASE( "entry" ) {
  404.           import char *dflt_enter_macro;
  405. !         
  406. !         dflt_enter_macro = parse_enter_macro(f, NL);
  407.           break;
  408.       }
  409.   
  410. --- 925,943 ----
  411.       
  412.       CASE( "entry" ) {
  413.           import char *dflt_enter_macro;
  414. !         group_header *gh, *get_group_search();
  415. !         char *macro;
  416. !         int i;
  417. !         
  418. !         macro = parse_enter_macro(f, NL);
  419. !         if (ARGTAIL) {
  420. !         for (i = 2; argv(i); i++) {
  421. !             start_group_search(argv(i));
  422. !             while (gh = get_group_search())
  423. !             gh->enter_macro = macro;
  424. !         }
  425. !         } else
  426. !         dflt_enter_macro = macro;
  427.           break;
  428.       }
  429.   
  430.  
  431. *** /usr/storm/nn6.3.9/kill.c    Fri Oct 20 23:24:51 1989
  432. --- kill.c    Tue Oct 24 10:11:54 1989
  433. ***************
  434. *** 6,11 ****
  435. --- 6,13 ----
  436.    * kill file handling
  437.    */
  438.   
  439. + export int killed_articles;
  440.   char KILL_FILE[] =     "kill";
  441.   char COMPILED_KILL[] =    "KILL.COMP";
  442.   
  443. ***************
  444. *** 94,102 ****
  445.           if (quick_match(string, kl->kill_pattern) == NULL)
  446.           continue;
  447.       
  448. !     if (kl->kill_flag & AUTO_KILL)
  449.           return 1;
  450.       ah->flag |= A_SELECT | A_AUTO;
  451.       break;
  452.       }
  453. --- 96,106 ----
  454.           if (quick_match(string, kl->kill_pattern) == NULL)
  455.           continue;
  456.       
  457. !     if (kl->kill_flag & AUTO_KILL) {
  458. !         killed_articles++;
  459.           return 1;
  460. !     }
  461. !     
  462.       ah->flag |= A_SELECT | A_AUTO;
  463.       break;
  464.       }
  465. ***************
  466. *** 145,150 ****
  467. --- 149,155 ----
  468.       } else
  469.           if (quick_match(string, kl->kill_pattern) == NULL)
  470.           continue;
  471. +     killed_articles++;
  472.       return 1;
  473.       }
  474.       
  475.  
  476. *** /usr/storm/nn6.3.7/macro.c    Fri Sep  8 12:46:46 1989
  477. --- macro.c    Fri Nov  3 16:01:39 1989
  478. ***************
  479. *** 212,218 ****
  480.       if (*lp == ':') {
  481.           lp++;
  482.           if (initial_set_commands) {
  483. !         if (!strncmp(lp, "set", 3) || !strncmp(lp, "unset", 5)) {
  484.               m_new(M_SET_COMMAND);
  485.               m->m_string = copy_str(lp);
  486.               break;
  487. --- 212,220 ----
  488.       if (*lp == ':') {
  489.           lp++;
  490.           if (initial_set_commands) {
  491. !         if (strncmp(lp, "local",  5) == 0 ||
  492. !             strncmp(lp, "set",    3) == 0 || 
  493. !             strncmp(lp, "unset",  5) == 0) {
  494.               m_new(M_SET_COMMAND);
  495.               m->m_string = copy_str(lp);
  496.               break;
  497.  
  498. *** /usr/storm/nn6.3.7/master.c    Fri Sep  8 12:46:47 1989
  499. --- master.c    Fri Nov  3 08:45:11 1989
  500. ***************
  501. *** 20,25 ****
  502. --- 20,27 ----
  503.    *
  504.    *    -E    expire by recolleting entire groups rather than copying files
  505.    *    -C    check consistency of database on start-up
  506. +  *    -b    include 'bad' articles (disables -B)
  507. +  *    -B    remove 'bad' articles (just unlink the files)
  508.    *
  509.    *    -I    initialize
  510.    *    -t    trace collection of each group
  511. ***************
  512. *** 26,31 ****
  513. --- 28,34 ----
  514.    *    -v    print version and exit
  515.    *    -u    update even if active is not modified
  516.    *    -w    send wakeup to real master
  517. +  *    -Ltypes    exclude 'types' entries from the log
  518.    *    -D    debug
  519.    */
  520.   
  521. ***************
  522. *** 44,51 ****
  523. --- 47,59 ----
  524.       debug_mode = 0;
  525.   
  526.   import int
  527. +     ignore_bad_articles,
  528. +     remove_bad_articles,
  529.       retry_on_error;
  530.   
  531. + import char
  532. +     *log_entry_filter;
  533.   export int
  534.       trace = 0,
  535.   #ifdef NNTP
  536. ***************
  537. *** 69,75 ****
  538. --- 77,86 ----
  539.   
  540.       'E', Bool_Option( clean_to_expire ),
  541.       'C', Bool_Option( check_on_startup ),
  542. +     'b', Bool_Option( ignore_bad_articles ),
  543. +     'B', Bool_Option( remove_bad_articles ),
  544.   
  545. +     'L', String_Option( log_entry_filter ),
  546.       'D', Bool_Option( debug_mode ),
  547.       't', Bool_Option( trace ),
  548.   
  549.  
  550. *** /usr/storm/nn6.3.9/menu.c    Fri Oct 20 23:24:53 1989
  551. --- menu.c    Thu Nov  9 12:36:36 1989
  552. ***************
  553. *** 19,25 ****
  554.   export int  slow_mode       = 0;    /* mark selected articles with *s */
  555.   export int  re_layout      = 0; /* Re: format presentation on menus */
  556.   export int  collapse_subject = 25; /* collapse long subjects at position */
  557. ! export int  conf_group_entry  = 0;    /* ask whether group should be entered */
  558.   
  559.   export char *delayed_msg = NULL;    /* give to msg() after redraw */
  560.   export long dl_msg_arg = 0;        /* optional arg to delayed_msg */
  561. --- 19,26 ----
  562.   export int  slow_mode       = 0;    /* mark selected articles with *s */
  563.   export int  re_layout      = 0; /* Re: format presentation on menus */
  564.   export int  collapse_subject = 25; /* collapse long subjects at position */
  565. ! export int  conf_group_entry  = 0; /* ask whether group should be entered */
  566. ! export int  auto_preview_mode = 0; /* preview rather than select */
  567.   
  568.   export char *delayed_msg = NULL;    /* give to msg() after redraw */
  569.   export long dl_msg_arg = 0;        /* optional arg to delayed_msg */
  570. ***************
  571. *** 58,63 ****
  572. --- 59,65 ----
  573.   #define    REMOVE    5
  574.   #define CANCEL    6
  575.   #define    ON_LEAVE 7
  576. + #define ON_READ 8
  577.   
  578.   static int how;
  579.   
  580. ***************
  581. *** 122,127 ****
  582. --- 124,135 ----
  583.       putchar((ah->flag & A_CANCEL) ? '#' : ' ');
  584.       return;
  585.   
  586. +      case ON_READ:
  587. +     if (cura < 0 || cura > numa) return;
  588. +     gotoxy(1, lno);
  589. +     putchar((ah->flag & A_READ) ? '.' : ' ');
  590. +     return;
  591.        case ON_LEAVE:
  592.       if (cura < 0 || cura > numa) return;
  593.       gotoxy(1, lno);
  594. ***************
  595. *** 314,320 ****
  596.       char *fmt;
  597.       
  598.       if (first <= start || n <= 0)
  599. !     if (last >= end) 
  600.           return "All";
  601.       else
  602.           fmt = "Top %d%%";
  603. --- 322,328 ----
  604.       char *fmt;
  605.       
  606.       if (first <= start || n <= 0)
  607. !     if (last >= end || n <= 0) 
  608.           return "All";
  609.       else
  610.           fmt = "Top %d%%";
  611. ***************
  612. *** 352,357 ****
  613. --- 360,367 ----
  614.   #define    menu_return(cmd) \
  615.       { menu_cmd = (cmd); goto menu_exit; }
  616.   
  617. +     flush_input();
  618. +     
  619.       o_firsta = firsta;
  620.       o_mode = in_menu_mode;
  621.       in_menu_mode = 1;
  622. ***************
  623. *** 876,881 ****
  624. --- 886,893 ----
  625.         case K_ARTICLE_ID:
  626.        if (numa < 0) goto nextmenu;
  627.   
  628. +      if (auto_preview_mode) goto auto_preview;
  629. +      
  630.        cura = article_id; 
  631.        how = TOGGLE;
  632.        mark();
  633. ***************
  634. *** 1057,1070 ****
  635.            article_id = cura;
  636.        }
  637.   
  638.        temp = prompt_line;
  639.   
  640.         preview_next:
  641. !      ah = articles[firsta+article_id];
  642. !      cura = article_id + 1;
  643.        
  644.        no_raw();
  645. !      switch (more(ah, MM_PREVIEW, prompt_line)) {
  646.            
  647.         case MC_DO_KILL:
  648.            if (!do_auto_kill()) break;
  649. --- 1069,1090 ----
  650.            article_id = cura;
  651.        }
  652.   
  653. +       auto_preview:
  654.        temp = prompt_line;
  655.   
  656.         preview_next:
  657. !      cura = article_id;
  658. !      ah = articles[firsta+cura];
  659.        
  660.        no_raw();
  661. !      menu_cmd = more(ah, MM_PREVIEW, prompt_line);
  662. !      if (auto_preview_mode && ah->flag & A_READ && prompt_line >= 0) {
  663. !          how = ON_READ;
  664. !          mark();
  665. !      }
  666. !      next_cura = ++cura;
  667. !      
  668. !      switch (menu_cmd) {
  669.            
  670.         case MC_DO_KILL:
  671.            if (!do_auto_kill()) break;
  672. ***************
  673. *** 1084,1096 ****
  674.            do_auto_select((regexp *)NULL, 2);
  675.            /* FALL THRU */
  676.   
  677. -       case MC_REDRAW:
  678. -          next_cura = cura;
  679. -          goto redraw;
  680. -          
  681. -       case MC_NO_REDRAW:
  682. -          break;
  683. -          
  684.         case MC_QUIT:
  685.            menu_return( ME_QUIT );
  686.   
  687. --- 1104,1109 ----
  688. ***************
  689. *** 1103,1108 ****
  690. --- 1116,1123 ----
  691.         case MC_PREVIEW_NEXT:
  692.            if (prompt_line < 0) {    /* redrawn screen ! */
  693.            if ((firsta + cura) >= n_articles) goto redraw;
  694. +          if (auto_preview_mode &&
  695. +              (articles[firsta+cura]->flag & A_SAME) == 0) goto redraw;
  696.            prompt_line = Lines;
  697.            } else {
  698.            if (ah->flag & (A_LEAVE | A_LEAVE_NEXT)) {
  699. ***************
  700. *** 1112,1117 ****
  701. --- 1127,1134 ----
  702.                cura++;
  703.            }
  704.            if (cura > numa) break;
  705. +          if (auto_preview_mode &&
  706. +              (articles[firsta+cura]->flag & A_SAME) == 0) break;
  707.            prompt_line = temp;
  708.            }
  709.            article_id = cura;
  710. ***************
  711. *** 1123,1128 ****
  712. --- 1140,1146 ----
  713.            goto preview_other;
  714.            
  715.         default:    
  716. +          if (prompt_line < 0) goto redraw;
  717.            break;
  718.        }
  719.        
  720.  
  721. *** /usr/storm/nn6.3.9/more.c    Fri Oct 20 23:24:55 1989
  722. --- more.c    Thu Nov  9 12:27:23 1989
  723. ***************
  724. *** 18,23 ****
  725. --- 18,24 ----
  726.   import int  preview_window;
  727.   import int  novice;
  728.   import int  slow_mode;
  729. + import int  auto_preview_mode;
  730.   
  731.   import char *delayed_msg;
  732.   import long dl_msg_arg;
  733. ***************
  734. *** 1093,1105 ****
  735.       if ((mode & MM_PREVIEW) && more_cmd != MC_QUIT) {
  736.       gotoxy(0, screen_offset);
  737.       clrpage(screen_offset);
  738. !     if (more_cmd == MC_PREVIEW_NEXT ||
  739. !         more_cmd == MC_DO_SELECT || more_cmd == MC_DO_KILL) {
  740. !         if (screen_offset == 0) prompt_line = -1;
  741. !     } else {
  742. !         if (screen_offset == 0) return MC_REDRAW;
  743. !         if (more_cmd != MC_PREVIEW_OTHER) return MC_NO_REDRAW;
  744.       }
  745.       }
  746.       
  747.       return more_cmd;
  748. --- 1094,1105 ----
  749.       if ((mode & MM_PREVIEW) && more_cmd != MC_QUIT) {
  750.       gotoxy(0, screen_offset);
  751.       clrpage(screen_offset);
  752. !     if (auto_preview_mode) {
  753. !         if ((ah->flag & (A_LEAVE | A_LEAVE_NEXT)) == 0)
  754. !         ah->flag |= A_READ;
  755. !         if (more_cmd == MC_NEXT) more_cmd = MC_PREVIEW_NEXT;
  756.       }
  757. +     if (screen_offset == 0) prompt_line = -1;
  758.       }
  759.       
  760.       return more_cmd;
  761.  
  762. *** /usr/storm/nn6.3.7/nn.c    Fri Sep  8 12:46:50 1989
  763. --- nn.c    Sun Oct 22 20:43:11 1989
  764. ***************
  765. *** 117,133 ****
  766.       init_key_map();
  767.       init_execute();
  768.       init_macro();
  769.       
  770.   #ifdef NNTP
  771.       nntp_check();
  772.   #endif
  773.       if (enter_admin_mode) {
  774.       if (argc == 1) {
  775.           init_term();
  776.           visit_init_file(0);
  777.       }
  778. -     open_master(OPEN_READ);
  779. -     visit_active_file();
  780.       admin_mode(argv[1]);
  781.       nn_exit(0);
  782.       }
  783. --- 117,133 ----
  784.       init_key_map();
  785.       init_execute();
  786.       init_macro();
  787. +     open_master(OPEN_READ);
  788.       
  789.   #ifdef NNTP
  790.       nntp_check();
  791.   #endif
  792.       if (enter_admin_mode) {
  793. +     visit_active_file();
  794.       if (argc == 1) {
  795.           init_term();
  796.           visit_init_file(0);
  797.       }
  798.       admin_mode(argv[1]);
  799.       nn_exit(0);
  800.       }
  801. ***************
  802. *** 151,158 ****
  803.           print_version("Release %R.%V.%P #%U,  Kim F. Storm, 1989\n\n");
  804.       }
  805.   
  806. -     open_master(OPEN_READ);
  807. -     
  808.       if (also_read_articles) {
  809.       if (article_limit < 0) 
  810.           article_limit = also_read_articles;
  811. --- 151,156 ----
  812.  
  813. *** /usr/storm/nn6.3.9/nn.1    Fri Oct 20 23:24:58 1989
  814. --- nn.1    Fri Nov 17 19:16:23 1989
  815. ***************
  816. *** 903,909 ****
  817.       || cd ~/src/nn ; patch
  818.   .br
  819.   .LP
  820. ! The following symbols are expanded in a file name:
  821.   .TP
  822.   .B $F
  823.   will be expanded to the name of the current group with the periods
  824. --- 903,909 ----
  825.       || cd ~/src/nn ; patch
  826.   .br
  827.   .LP
  828. ! The following symbols are expanded in a file name or command:
  829.   .TP
  830.   .B $F
  831.   will be expanded to the name of the current group with the periods
  832. ***************
  833. *** 920,925 ****
  834. --- 920,927 ----
  835.   .B $N
  836.   will be expanded to the (local) article number, e.g. 1099.  In
  837.   selection mode it is only allowed at the end of the file name!
  838. + .B $(VAR)
  839. + is replaced by the string value of the environment variable \fIVAR\fP.
  840.   .LP
  841.   Using these symbols, a simple naming scheme for `default folder name' is
  842.   .B +$G
  843. ***************
  844. *** 1429,1434 ****
  845. --- 1431,1439 ----
  846.   .TP
  847.   .B %
  848.   Same as $A.
  849. + .TP
  850. + .B $(VAR)
  851. + is replaced by the string value of the environment variable \fIVAR\fP.
  852.   .LP
  853.   When the shell command is completed, you will be asked to hit any key
  854.   to continue.  If you hit the 
  855. ***************
  856. *** 1523,1528 ****
  857. --- 1528,1540 ----
  858.   Provide online help on the specified subject.  If you omit the
  859.   subject, a list of the available topics will be given.
  860.   .TP
  861. + \fB:local\fP \fIvariable\fP [ \fIvalue\fP ]
  862. + Make the variable local to the current group.  Subsequent changes to
  863. + the variable will only be effective until the current group is left.
  864. + If a value is specified, it will be assigned to the local variable.
  865. + To assign a new value to a boolean variable, the values \fBon\fP and
  866. + \fBoff\fP must be used.
  867. + .TP
  868.   \fB:man\fP
  869.   Call up the online manual.  The manual is presented as a normal folder
  870.   with the program name in the `From' field and the section title in the
  871. ***************
  872. *** 1712,1717 ****
  873. --- 1724,1740 ----
  874.   .B :set
  875.   command without arguments.
  876.   .LP
  877. + Variables are global by default, but a local instantiation of the
  878. + variable can be created using the \fB:local\fP command.  The local
  879. + variable will overlay the global variable as long as the current group
  880. + is active, i.e. the global variable will be used again when you exit
  881. + the current group.  The initial value of the local variable will be
  882. + the same as the global variable, unless a new value is specified in
  883. + the \fB:local\fP command:
  884. + .sp 0.5v
  885. +     \fB:local\fP \fIvariable\fP [ \fIvalue\fP ]
  886. + .sp 0.5v
  887. + .LP
  888.   The following variables are available:
  889.   .TP
  890.   \fBalso-subgroups\fP    (boolean, default true)
  891. ***************
  892. *** 1725,1730 ****
  893. --- 1748,1763 ----
  894.   asterisk `*', e.g. comp.unix*, will include the group as well as all
  895.   subgroups independently of the setting of \fBalso-subgroups\fP.
  896.   .TP
  897. + \fBauto-preview-mode\fP    (boolean, default false)
  898. + Enables \fIAuto Preview Mode\fP.  In this mode, selecting an article
  899. + on the menu using its article id (letter a-z) will enter preview mode
  900. + on that article immediately.  Furthermore, the `n' {\fBnext-article\fP}
  901. + command will preview the next article on the menu only if it has the
  902. + same subject as the current article; otherwise, it will return to the
  903. + menu with the cursor placed on the next article.  The \fBcontinue\fP
  904. + command at the end of the article and the `=' {\fBgoto-menu\fP}
  905. + returns to the menu immediately as usual.
  906. + .TP
  907.   \fBbackup\fP    (boolean, default true)
  908.   Backup the rc file on start-up.  Setting 
  909.   .B backup
  910. ***************
  911. *** 1888,1894 ****
  912.   when \fInn\fP is prompting for a string, e.g. a file name.
  913.   .TP
  914.   \fBlayout\fP \fInumber\fP    (integer, default 1)
  915. ! Set the menu layout.  The argument must be a number between 0 and 3.
  916.   .TP
  917.   \fBlimit\fP \fImax-articles\fP    (integer, default infinite)
  918.   .I Limit
  919. --- 1921,1927 ----
  920.   when \fInn\fP is prompting for a string, e.g. a file name.
  921.   .TP
  922.   \fBlayout\fP \fInumber\fP    (integer, default 1)
  923. ! Set the menu layout.  The argument must be a number between 0 and 5.
  924.   .TP
  925.   \fBlimit\fP \fImax-articles\fP    (integer, default infinite)
  926.   .I Limit
  927. ***************
  928. *** 2956,2965 ****
  929.   The commands are executed if the TERM environment variable contains
  930.   the value specified by \fIterm-type\fP.
  931.   .TP
  932. ! \fBon entry\fP
  933.   .br
  934.   These commands (macro format!) are executed every time \fInn\fP enters a
  935. ! news group.  The `:set' and `:unset' commands at the beginning of the
  936.   command group are executed \fIbefore\fP \fInn\fP collects the articles
  937.   in the group, so it is possible to set variables like
  938.   \fBcross-post\fP.  The other commands, and :set/:unset commands that
  939. --- 2989,3004 ----
  940.   The commands are executed if the TERM environment variable contains
  941.   the value specified by \fIterm-type\fP.
  942.   .TP
  943. ! \fBon entry\fP [ \fIgroup list\fP ]
  944.   .br
  945.   These commands (macro format!) are executed every time \fInn\fP enters a
  946. ! news group.  If a group list is not specified, the commands are
  947. ! associated with all groups which don't have its own entry macro
  948. ! specified in the group sequence.  Otherwise, the entry macro will be
  949. ! associated with the groups in the list.  The group list is specified
  950. ! using the meta-notations described in the presentation sequence section.
  951. ! .sp 0.5v
  952. ! The `:set', `:unset', and `:local' commands at the beginning of the 
  953.   command group are executed \fIbefore\fP \fInn\fP collects the articles
  954.   in the group, so it is possible to set variables like
  955.   \fBcross-post\fP.  The other commands, and :set/:unset commands that
  956. ***************
  957. *** 2967,2979 ****
  958.   \fIafter\fP the first menu page is presented.
  959.   .sp 0.5v
  960.   .nf
  961. !     \fBon entry\fP
  962. !         :unset cross-post
  963.       \fBend\fP        
  964.   .fi
  965. - .sp 0.5v
  966. - The `entry' command group is \fInot\fP executed if the group has its
  967. - own entry action specified in the presentation sequence (see below).
  968.   .SH GROUP PRESENTATION SEQUENCE
  969.   News groups are normally presented in the sequence defined in the
  970.   system-wide 
  971. --- 3006,3015 ----
  972.   \fIafter\fP the first menu page is presented.
  973.   .sp 0.5v
  974.   .nf
  975. !     \fBon entry\fP comp.sources* alt.sources
  976. !         :local cross-post on
  977.       \fBend\fP        
  978.   .fi
  979.   .SH GROUP PRESENTATION SEQUENCE
  980.   News groups are normally presented in the sequence defined in the
  981.   system-wide 
  982. ***************
  983. *** 3097,3103 ****
  984.   .TP
  985.   \&< group.name
  986.   Place the group (and its subgroups) at the beginning of the
  987. ! presentation sequence.
  988.   .TP
  989.   \&> group.name
  990.   Place the group (and its subgroups) after all other groups that are
  991. --- 3133,3141 ----
  992.   .TP
  993.   \&< group.name
  994.   Place the group (and its subgroups) at the beginning of the
  995. ! presentation sequence.  Notice that each `<' entry will place the
  996. ! group(s) at the beginning of the current sequence, i.e. < A < B < C
  997. ! will generate the sequence C B A.
  998.   .TP
  999.   \&> group.name
  1000.   Place the group (and its subgroups) after all other groups that are
  1001.  
  1002. *** /usr/storm/nn6.3.7/nnadmin.1m    Fri Sep  8 12:46:50 1989
  1003. --- nnadmin.1m    Thu Nov 16 14:40:25 1989
  1004. ***************
  1005. *** 523,528 ****
  1006. --- 523,529 ----
  1007.   .br
  1008.   .DT
  1009.   .ta \w'$db/DATA/\fInnn\fP.dx'u+3m
  1010. + .\"ta 0 16
  1011.   $db/MASTER    Database master index
  1012.   .br
  1013.   $db/GROUPS    News group names in MASTER file order
  1014.  
  1015. *** /usr/storm/nn6.3.7/nncheck.1    Fri Sep  8 12:46:50 1989
  1016. --- nncheck.1    Thu Nov 16 14:40:25 1989
  1017. ***************
  1018. *** 57,62 ****
  1019. --- 57,63 ----
  1020.   .sp 0.5v
  1021.   .DT
  1022.   .ta 1i 2i
  1023. + .\"ta 4 12
  1024.   .nf
  1025.       \fB%-code\fP    \fBresulting output\fP
  1026.   .sp 0.5v
  1027. ***************
  1028. *** 85,90 ****
  1029. --- 86,92 ----
  1030.   .SH FILES
  1031.   .DT
  1032.   .ta \w'$db/MASTER'u+6m
  1033. + .\"ta 0 12
  1034.   ~/.nn/rc    The record of read articles
  1035.   .br
  1036.   $db/MASTER    The database master index
  1037.  
  1038. *** /usr/storm/nn6.3.7/nngoback.1    Fri Sep  8 12:46:50 1989
  1039. --- nngoback.1    Thu Nov 16 14:40:24 1989
  1040. ***************
  1041. *** 64,69 ****
  1042. --- 64,70 ----
  1043.   .SH FILES
  1044.   .DT
  1045.   .ta \w'$lib/date_regexp'u+3m
  1046. + .\"ta 0 20
  1047.   ~/.nn/rc    The record of read articles.
  1048.   .br
  1049.   ~/.nn/rc.bak1    The original rc file before goback.
  1050.  
  1051. *** /usr/storm/nn6.3.7/nngrep.1    Fri Sep  8 12:46:50 1989
  1052. --- nngrep.1    Thu Nov 16 14:40:24 1989
  1053. ***************
  1054. *** 29,34 ****
  1055. --- 29,35 ----
  1056.   .SH FILES
  1057.   .DT
  1058.   .ta \w'~/.nn/rc.bak'u+3m
  1059. + .\"ta 0 12
  1060.   ~/.nn/rc    The record of read articles
  1061.   .DT
  1062.   .SH SEE ALSO
  1063.  
  1064. *** /usr/storm/nn6.3.7/nnmaster.1m    Fri Sep  8 12:46:51 1989
  1065. --- nnmaster.1m    Thu Nov 16 14:40:23 1989
  1066. ***************
  1067. *** 17,27 ****
  1068.   [ \-\fBr [ \fP\fIN\fP ] ]
  1069.   [ \-\fBe\fP\fIN\fP ] 
  1070.   [ \-\fBy\fP\fIN\fP ] 
  1071. ! [ \-\fBf\fP ]
  1072. ! [ \-\fBC\fP ]
  1073. ! [ \-\fBE\fP ]
  1074. ! [ \-\fBu\fP ]
  1075. ! [ \-\fBt\fP ]
  1076.   .SH DESCRIPTION
  1077.   .I nnmaster
  1078.   is the daemon which is responsible for building and maintaining the
  1079. --- 17,24 ----
  1080.   [ \-\fBr [ \fP\fIN\fP ] ]
  1081.   [ \-\fBe\fP\fIN\fP ] 
  1082.   [ \-\fBy\fP\fIN\fP ] 
  1083. ! [ \-\fBL\fP\fItypes\fP ]
  1084. ! [ \-\fBBbCEfut\fP ]
  1085.   .SH DESCRIPTION
  1086.   .I nnmaster
  1087.   is the daemon which is responsible for building and maintaining the
  1088. ***************
  1089. *** 87,92 ****
  1090. --- 84,102 ----
  1091.   Run \fInnmaster\fP in foreground in daemon mode (see \-\fBr\fP).
  1092.   Useful if \fInnmaster\fP is invoked from inittab.
  1093.   .TP
  1094. + .B \-b
  1095. + Normally, articles without a proper news header (no Newsgroups: line)
  1096. + are ignored.  Specifying the \-\fBb\fP option causes these `bad'
  1097. + articles to be included in the database (normally with no sender or
  1098. + subject).
  1099. + .TP
  1100. + .B \-B
  1101. + Remove `bad' articles.  Sometimes, articles without a header ends up
  1102. + in the news spool directory.  These articles have no article id, and
  1103. + therefore, they will never be expired by \fBexpire\fP(8).  This option
  1104. + will allow the \fInnmaster\fP to silently remove these articles (a `B'
  1105. + entry will occur in the log file).
  1106. + .TP
  1107.   \-\fBe\fP \fIart\fP
  1108.   .br
  1109.   Run internal
  1110. ***************
  1111. *** 138,143 ****
  1112. --- 148,157 ----
  1113.   keep news for a long time, you should not use the \-E option
  1114.   without a little thought. 
  1115.   .TP
  1116. + \-\fBL\fP \fItypes\fP
  1117. + Exclude the specified entry types from the log file.  This is normally
  1118. + used to exclude the 'C'ollecting and e'X'pire entries (\-\fBL\fPCX).
  1119. + .TP
  1120.   .B \-I
  1121.   Initialize database.  This option will erase an existing database, and
  1122.   create an empty database containing entries for the currently known
  1123. ***************
  1124. *** 173,178 ****
  1125. --- 187,193 ----
  1126.   .LP
  1127.   .DT
  1128.   .ta \w'$db/DATA/\fInnn\fP.[dx]'u+3m
  1129. + .\"ta 0 20
  1130.   $db/MASTER    Database master index
  1131.   .br
  1132.   $db/GROUPS    News group names in MASTER file order
  1133.  
  1134. *** /usr/storm/nn6.3.7/nntidy.1    Fri Sep  8 12:46:51 1989
  1135. --- nntidy.1    Thu Nov 16 14:40:22 1989
  1136. ***************
  1137. *** 17,22 ****
  1138. --- 17,23 ----
  1139.   .SH FILES
  1140.   .DT
  1141.   .ta \w'~/.nn/rc.bak'u+3m
  1142. + .\"ta 0 20
  1143.   ~/.nn/rc    The record of read articles
  1144.   .br
  1145.   ~/.nn/rc.bak    The original rc file before tidy
  1146.  
  1147. *** /usr/storm/nn6.3.7/nnusage.1m    Fri Sep  8 12:46:51 1989
  1148. --- nnusage.1m    Thu Nov 16 14:40:22 1989
  1149. ***************
  1150. *** 23,28 ****
  1151. --- 23,29 ----
  1152.   .SH FILES
  1153.   .DT
  1154.   .ta \w'$lib/Log'u+3m
  1155. + .\"ta 0 20
  1156.   $lib/Log    The log file
  1157.   .DT
  1158.   .SH SEE ALSO
  1159.  
  1160. *** /usr/storm/nn6.3.7/rc.c    Fri Sep  8 12:46:54 1989
  1161. --- rc.c    Sun Oct 22 17:43:54 1989
  1162. ***************
  1163. *** 377,383 ****
  1164.           n = unread_articles;
  1165.           add_unread(gh, 1);
  1166.           if (trace)
  1167. !         printf("%s: %d\n", gh->group_name, unread_articles - n);
  1168.       }
  1169.       }
  1170.   }
  1171. --- 377,383 ----
  1172.           n = unread_articles;
  1173.           add_unread(gh, 1);
  1174.           if (trace)
  1175. !         printf("%6d %s\n", unread_articles - n, gh->group_name);
  1176.       }
  1177.       }
  1178.   }
  1179.  
  1180. *** /usr/storm/nn6.3.9/save.c    Fri Oct 20 23:25:04 1989
  1181. --- save.c    Wed Oct 25 10:23:21 1989
  1182. ***************
  1183. *** 18,23 ****
  1184. --- 18,24 ----
  1185.   export int  save_report = 1;
  1186.   export int  quick_save = 0;
  1187.   export int  conf_append = 0;
  1188. + export int  conf_create = 1;
  1189.   
  1190.   export char *save_counter_format = "%d";    /* format of save counter */
  1191.   
  1192. ***************
  1193. *** 241,247 ****
  1194.           last = strrchr(start, '/');
  1195.           /* last != NULL => non-existing directories */
  1196.           
  1197. !         if (!(save_mode & SEPARATE_FILES) || last) {
  1198.               printf("\rCreate ");
  1199.               for (np = save_name; *np; np++) {
  1200.               if (np == start) putchar('\"');
  1201. --- 242,248 ----
  1202.           last = strrchr(start, '/');
  1203.           /* last != NULL => non-existing directories */
  1204.           
  1205. !         if (conf_create && (!(save_mode & SEPARATE_FILES) || last)) {
  1206.               printf("\rCreate ");
  1207.               for (np = save_name; *np; np++) {
  1208.               if (np == start) putchar('\"');
  1209.  
  1210. *** /usr/storm/nn6.3.7/sequence.c    Fri Sep  8 12:46:59 1989
  1211. --- sequence.c    Wed Oct 25 12:43:06 1989
  1212. ***************
  1213. *** 80,85 ****
  1214. --- 80,86 ----
  1215.       found = 0;
  1216.       start_group_search(group);
  1217.       while (gh = get_group_search()) {
  1218. +         gh->group_flag |= G_DONE;
  1219.           if ((gh->group_flag & G_SUBSCRIPTION) == 0 && !also_unsub_groups)
  1220.           continue;
  1221.           found++;
  1222. ***************
  1223. *** 311,319 ****
  1224.       start_group_search(group);
  1225.       
  1226.       while (gh = get_group_search()) {
  1227.   
  1228.           gh->save_file = dflt_save;
  1229. !         gh->enter_macro = enter_macro;
  1230.           
  1231.           if (group_name_args == 0 &&
  1232.           (gh->group_flag & G_SUBSCRIPTION) == 0 && !also_unsub_groups)
  1233. --- 312,322 ----
  1234.       start_group_search(group);
  1235.       
  1236.       while (gh = get_group_search()) {
  1237. +         gh->group_flag |= G_DONE;
  1238.   
  1239.           gh->save_file = dflt_save;
  1240. !         if (gh->enter_macro == NULL) /* not set by "on entry" */
  1241. !         gh->enter_macro = enter_macro;
  1242.           
  1243.           if (group_name_args == 0 &&
  1244.           (gh->group_flag & G_SUBSCRIPTION) == 0 && !also_unsub_groups)
  1245. ***************
  1246. *** 397,402 ****
  1247. --- 400,406 ----
  1248.   static int gs_length, gs_index, gs_mode;
  1249.   static group_header *gs_only_group = NULL;
  1250.   
  1251. + #define GS_PREFIX0    0    /* group (or group*) */
  1252.   #define    GS_PREFIX    1    /* group. */
  1253.   #define    GS_SUFFIX    2    /* .group */
  1254.   #define GS_INFIX    3    /* .group. */
  1255. ***************
  1256. *** 403,409 ****
  1257.   #define GS_NEW_GROUP    4    /* new group */
  1258.   #define GS_ALL        5    /* all / . */
  1259.   
  1260. ! static start_group_search(group)
  1261.   char *group;
  1262.   {
  1263.       char *dot;
  1264. --- 407,413 ----
  1265.   #define GS_NEW_GROUP    4    /* new group */
  1266.   #define GS_ALL        5    /* all / . */
  1267.   
  1268. ! start_group_search(group)
  1269.   char *group;
  1270.   {
  1271.       char *dot;
  1272. ***************
  1273. *** 425,431 ****
  1274.       gs_mode = GS_ALL;
  1275.       gs_length = 0;
  1276.       } else {
  1277. !     gs_mode = GS_PREFIX;
  1278.       
  1279.       if (strncmp(group, "all.", 4) == 0) group += 3;
  1280.       
  1281. --- 429,435 ----
  1282.       gs_mode = GS_ALL;
  1283.       gs_length = 0;
  1284.       } else {
  1285. !     gs_mode = GS_PREFIX0;
  1286.       
  1287.       if (strncmp(group, "all.", 4) == 0) group += 3;
  1288.       
  1289. ***************
  1290. *** 433,440 ****
  1291.       
  1292.       if ((dot = strrchr(group, '.')) != NULL && dot != group) {
  1293.           if (dot[1] == NUL || strcmp(dot+1, "all") == 0) {
  1294. !         *dot = NUL;
  1295. !         if (gs_mode == GS_SUFFIX) gs_mode = GS_INFIX;
  1296.           }
  1297.       }
  1298.       
  1299. --- 437,444 ----
  1300.       
  1301.       if ((dot = strrchr(group, '.')) != NULL && dot != group) {
  1302.           if (dot[1] == NUL || strcmp(dot+1, "all") == 0) {
  1303. !         dot[1] = NUL;
  1304. !         gs_mode = (gs_mode == GS_SUFFIX) ? GS_INFIX : GS_PREFIX;
  1305.           }
  1306.       }
  1307.       
  1308. ***************
  1309. *** 447,453 ****
  1310.   }
  1311.   
  1312.   
  1313. ! static group_header *get_group_search()
  1314.   {
  1315.       register group_header *gh;
  1316.       register int c, tail;
  1317. --- 451,457 ----
  1318.   }
  1319.   
  1320.   
  1321. ! group_header *get_group_search()
  1322.   {
  1323.       register group_header *gh;
  1324.       register int c, tail;
  1325. ***************
  1326. *** 456,462 ****
  1327.       gh = gs_only_group;
  1328.       gs_only_group = NULL;
  1329.       if (gh->group_flag & (G_DONE | G_NO_DIRECTORY)) return NULL;
  1330. -     gh->group_flag |= G_DONE;
  1331.       return gh;
  1332.       }
  1333.       
  1334. --- 460,465 ----
  1335. ***************
  1336. *** 474,481 ****
  1337.           if ((gh->group_flag & G_NEW) == 0) continue;
  1338.           break;
  1339.           
  1340. !      case GS_PREFIX:
  1341.           if ((c = (gh->group_name)[gs_length]) != NUL && c != '.') continue;
  1342.           if (strncmp(gh->group_name, gs_group, gs_length)) continue;
  1343.           break;
  1344.           
  1345. --- 477,485 ----
  1346.           if ((gh->group_flag & G_NEW) == 0) continue;
  1347.           break;
  1348.           
  1349. !      case GS_PREFIX0:
  1350.           if ((c = (gh->group_name)[gs_length]) != NUL && c != '.') continue;
  1351. +      case GS_PREFIX:
  1352.           if (strncmp(gh->group_name, gs_group, gs_length)) continue;
  1353.           break;
  1354.           
  1355. ***************
  1356. *** 492,499 ****
  1357.       }
  1358.   
  1359.       gs_more_groups--;
  1360. -     gh->group_flag |= G_DONE;
  1361. -     
  1362.       return gh;
  1363.       }
  1364.       
  1365. --- 496,501 ----
  1366.  
  1367. *** /usr/storm/nn6.3.9/term.c    Fri Oct 20 23:25:06 1989
  1368. --- term.c    Wed Oct 25 10:24:17 1989
  1369. ***************
  1370. *** 688,700 ****
  1371. --- 688,708 ----
  1372.   }
  1373.   #endif /* CBREAK */
  1374.   
  1375. + static int do_flush_input = 0;
  1376.   flush_input()
  1377.   {
  1378.   #ifdef HAVE_TERMIO
  1379.       ioctl(0, TCFLSH, 0);
  1380. +     do_flush_input = 1;
  1381. + #else
  1382. + #ifdef FREAD
  1383. +     int arg = FREAD;
  1384. +     ioctl(0, TIOCFLUSH, &arg);
  1385.   #else
  1386.       ioctl(0, TIOCFLUSH, 0);
  1387.   #endif
  1388. + #endif
  1389.   }
  1390.       
  1391.   int enable_stop = 1;
  1392. ***************
  1393. *** 721,726 ****
  1394. --- 729,739 ----
  1395.   #ifdef KEY_BURST
  1396.       static char cbuf[KEY_BURST], *cp;
  1397.       static int n = 0;
  1398. +     if (do_flush_input) {
  1399. +     do_flush_input = 0;
  1400. +     n = 0;
  1401. +     }
  1402.   #else
  1403.       int n;
  1404.       unsigned char first_key;
  1405.  
  1406. *** /usr/storm/nn6.3.9/variable.c    Fri Oct 20 23:25:08 1989
  1407. --- variable.c    Fri Nov 17 18:51:47 1989
  1408. ***************
  1409. *** 30,38 ****
  1410. --- 30,40 ----
  1411.   import int            /* boolean variables */
  1412.       also_cross_postings,
  1413.       also_subgroups,
  1414. +     auto_preview_mode,
  1415.       compress_mode,
  1416.       conf_append,
  1417.       conf_auto_quit,
  1418. +     conf_create,
  1419.       conf_dont_sleep,
  1420.       conf_group_entry,
  1421.       delay_redraw,
  1422. ***************
  1423. *** 104,109 ****
  1424. --- 106,112 ----
  1425.       char **var_addr;
  1426.   } variables[] = {
  1427.       "also-subgroups",    V_BOOLEAN | V_INIT, 0,    (char **)&also_subgroups,
  1428. +     "auto-preview-mode",V_BOOLEAN,    0,    (char **)&auto_preview_mode,
  1429.       "backup",        V_BOOLEAN | V_INIT, 0,    (char **)&keep_rc_backup,
  1430.       "collapse-subject",    V_INTEGER,    3,    (char **)&collapse_subject,
  1431.       "columns",        V_INTEGER,    1,    (char **)&Columns,
  1432. ***************
  1433. *** 112,117 ****
  1434. --- 115,121 ----
  1435.       "compress",        V_BOOLEAN,    0,    (char **)&compress_mode,
  1436.       "confirm-append",    V_BOOLEAN,    0,    (char **)&conf_append,
  1437.       "confirm-auto-quit",V_BOOLEAN,    0,    (char **)&conf_auto_quit,
  1438. +     "confirm-create",    V_BOOLEAN,    0,    (char **)&conf_create,
  1439.       "confirm-entry",    V_BOOLEAN,    0,    (char **)&conf_group_entry,
  1440.       "confirm-messages",    V_BOOLEAN,    0,    (char **)&conf_dont_sleep,
  1441.       "cross-filter-seq",    V_BOOLEAN,    0,    (char **)&seq_cross_filtering,
  1442. ***************
  1443. *** 138,144 ****
  1444.       "lines",        V_INTEGER,    1,    (char **)&Lines,
  1445.       "long-menu",    V_BOOLEAN,    1,    (char **)&long_menu,
  1446.       "macro-debug",    V_BOOLEAN,    0,    (char **)¯o_debug,
  1447. !     "mail",        V_STRING,    0,    (char **)&mail_box,
  1448.       "mail-format",    V_BOOLEAN,    0,    (char **)&use_mail_folders,
  1449.       "mail-header",    V_STRING,    0,    (char **)&extra_mail_headers,
  1450.       "mail-record",    V_STRING,    2,    (char **)&mail_record,
  1451. --- 142,148 ----
  1452.       "lines",        V_INTEGER,    1,    (char **)&Lines,
  1453.       "long-menu",    V_BOOLEAN,    1,    (char **)&long_menu,
  1454.       "macro-debug",    V_BOOLEAN,    0,    (char **)¯o_debug,
  1455. !     "mail",        V_STRING,    2,    (char **)&mail_box,
  1456.       "mail-format",    V_BOOLEAN,    0,    (char **)&use_mail_folders,
  1457.       "mail-header",    V_STRING,    0,    (char **)&extra_mail_headers,
  1458.       "mail-record",    V_STRING,    2,    (char **)&mail_record,
  1459. ***************
  1460. *** 226,231 ****
  1461. --- 230,236 ----
  1462.       if (strncmp(variable, "no", 2) == 0) {
  1463.       on = !on;
  1464.       variable += 2;
  1465. +     if (variable[0] == '-') variable++;
  1466.       }
  1467.       
  1468.       if ((var = lookup_variable(variable)) == NULL) 
  1469. ***************
  1470. *** 262,269 ****
  1471.   
  1472.        case 2:
  1473.           if (on) {
  1474.           adjust(val_string);
  1475. !         if (val_string) STR_VAR = home_relative(val_string);
  1476.           } else
  1477.           STR_VAR = (char *)NULL;
  1478.           break;
  1479. --- 267,279 ----
  1480.   
  1481.        case 2:
  1482.           if (on) {
  1483. +         char exp_buf[FILENAME];
  1484. +         
  1485.           adjust(val_string);
  1486. !         if (val_string) {
  1487. !             if (expand_file_name(exp_buf, val_string))
  1488. !             STR_VAR = home_relative(exp_buf);
  1489. !         }
  1490.           } else
  1491.           STR_VAR = (char *)NULL;
  1492.           break;
  1493. ***************
  1494. *** 280,285 ****
  1495. --- 290,297 ----
  1496.       
  1497.        case V_BOOLEAN:
  1498.       
  1499. +     if (val_string) on = strncmp(val_string, "off", 3);
  1500.       switch (var->var_op) {
  1501.        case 0:
  1502.           BOOL_VAR = on;
  1503. ***************
  1504. *** 367,373 ****
  1505.   
  1506.   disp_variables()
  1507.   {
  1508. !     char *str, *key_name();
  1509.       int i, b;
  1510.       register struct variable_defs *var;
  1511.       
  1512. --- 379,385 ----
  1513.   
  1514.   disp_variables()
  1515.   {
  1516. !     char *str, *key_name(), *pushed;
  1517.       int i, b;
  1518.       register struct variable_defs *var;
  1519.       
  1520. ***************
  1521. *** 380,392 ****
  1522.       so_printf("\1Variable settings:\1");
  1523.   
  1524.       for (var = variables; var < &variables[TABLE_SIZE]; var++) {
  1525.       switch (VAR_TYPE) {
  1526.        case V_STRING:
  1527.           str = (var->var_op == 1) ? CBUF_VAR : STR_VAR;
  1528. !         if (str == NULL || *str == NUL) break;
  1529.           
  1530.           if (pg_next() < 0) goto out;
  1531. !         printf("%-20.20s = \"%s\"\n", var->var_name, str);
  1532.           break;
  1533.   
  1534.        case V_BOOLEAN:
  1535. --- 392,405 ----
  1536.       so_printf("\1Variable settings:\1");
  1537.   
  1538.       for (var = variables; var < &variables[TABLE_SIZE]; var++) {
  1539. +     pushed = var_on_stack(var) ? ">" : " ";
  1540.       switch (VAR_TYPE) {
  1541.        case V_STRING:
  1542.           str = (var->var_op == 1) ? CBUF_VAR : STR_VAR;
  1543. !         if (str == NULL) str = "";
  1544.           
  1545.           if (pg_next() < 0) goto out;
  1546. !         printf("%s %-20.20s = \"%s\"\n", pushed, var->var_name, str);
  1547.           break;
  1548.   
  1549.        case V_BOOLEAN:
  1550. ***************
  1551. *** 393,410 ****
  1552.           if (pg_next() < 0) goto out;
  1553.           b = BOOL_VAR;
  1554.           if (var->var_op == 2 || var->var_op == 4) b = !b;
  1555. !         printf("%s%s\n", b ? "" : "no ", var->var_name);
  1556.           break;
  1557.           
  1558.        case V_INTEGER:
  1559.           i = INT_VAR;
  1560.           if (pg_next() < 0) goto out;
  1561. !         printf("%-20.20s = %d\n", var->var_name, i);
  1562.           break;
  1563.           
  1564.        case V_KEY:
  1565.           if (pg_next() < 0) goto out;
  1566. !         printf("%-20.20s = %s\n", var->var_name, key_name(KEY_VAR));
  1567.           break;
  1568.           
  1569.        case V_SPECIAL:
  1570. --- 406,423 ----
  1571.           if (pg_next() < 0) goto out;
  1572.           b = BOOL_VAR;
  1573.           if (var->var_op == 2 || var->var_op == 4) b = !b;
  1574. !         printf("%s %-20.20s %s\n", pushed, var->var_name, b ? "" : "= off");
  1575.           break;
  1576.           
  1577.        case V_INTEGER:
  1578.           i = INT_VAR;
  1579.           if (pg_next() < 0) goto out;
  1580. !         printf("%s %-20.20s = %d\n", pushed, var->var_name, i);
  1581.           break;
  1582.           
  1583.        case V_KEY:
  1584.           if (pg_next() < 0) goto out;
  1585. !         printf("%s %-20.20s = %s\n", pushed, var->var_name, key_name(KEY_VAR));
  1586.           break;
  1587.           
  1588.        case V_SPECIAL:
  1589. ***************
  1590. *** 414,420 ****
  1591.            case 2:
  1592.           if (also_read_articles) {
  1593.               if (pg_next() < 0) goto out;
  1594. !             printf("%-20.20s = %d\n", var->var_name, article_limit);
  1595.           }
  1596.           break;
  1597.           }
  1598. --- 427,433 ----
  1599.            case 2:
  1600.           if (also_read_articles) {
  1601.               if (pg_next() < 0) goto out;
  1602. !             printf("%s %-20.20s = %d\n", pushed, var->var_name, article_limit);
  1603.           }
  1604.           break;
  1605.           }
  1606. ***************
  1607. *** 501,506 ****
  1608. --- 514,524 ----
  1609.       head = path;
  1610.       tail = path + index;
  1611.       while (*head && isspace(*head)) head++;
  1612. +     if (strncmp(head, "no", 2) == 0) {
  1613. +         head += 2;
  1614. +         if (*head == '-') head++;
  1615. +     }
  1616. +     
  1617.       help_var = var = variables;
  1618.       len = tail - head;
  1619.       
  1620. ***************
  1621. *** 542,544 ****
  1622. --- 560,714 ----
  1623.       return 0;
  1624.   }
  1625.   
  1626. + static struct var_stack {
  1627. +     struct var_stack *next;
  1628. +     struct variable_defs *v;
  1629. +     union {
  1630. +     int ivar;
  1631. +     int bool;
  1632. +     char key;
  1633. +     char *str;
  1634. +     } value;
  1635. + } *var_stack = NULL, *vs_pool = NULL;
  1636. + mark_var_stack()
  1637. + {
  1638. +     register struct var_stack *vs;
  1639. +     
  1640. +     if (vs_pool) {
  1641. +     vs = vs_pool;
  1642. +     vs_pool = vs->next;
  1643. +     } else {
  1644. +     vs = (struct var_stack *)calloc(1, sizeof(struct var_stack));
  1645. +     mem_check((char *)vs, 1, "var structure");
  1646. +     }
  1647. +     vs->next = var_stack;
  1648. +     var_stack = vs;
  1649. +     vs->v = NULL;
  1650. + }
  1651. + push_variable(variable)
  1652. + char *variable;
  1653. + {
  1654. +     register struct variable_defs *var;
  1655. +     register struct var_stack *vs;
  1656. +     
  1657. +     if (strncmp(variable, "no", 2) == 0) {
  1658. +     variable += 2;
  1659. +     if (variable[0] == '-') variable++;
  1660. +     }
  1661. +     
  1662. +     if ((var = lookup_variable(variable)) == NULL) {
  1663. +     msg("pushing unknown variable %s", variable);
  1664. +     return 0;
  1665. +     }    
  1666. +     mark_var_stack();
  1667. +     vs = var_stack;
  1668. +     vs->v = var;
  1669. +     
  1670. +     switch (VAR_TYPE) {
  1671. +     
  1672. +      case V_STRING:
  1673. +     switch (var->var_op) {
  1674. +      case 0:    /* if we update one of these variables,    */
  1675. +      case 2:    /* new storage will be allocated for it */
  1676. +      case 3:    /* so it is ok just to save the pointer */
  1677. +         vs->value.str = STR_VAR;
  1678. +         break;
  1679. +      case 1:    /* we free this memory when restored    */
  1680. +         vs->value.str = copy_str(CBUF_VAR);
  1681. +         break;
  1682. +     }
  1683. +     break;
  1684. +     
  1685. +      case V_BOOLEAN:
  1686. +     vs->value.bool = BOOL_VAR;
  1687. +     break;
  1688. +     
  1689. +      case V_INTEGER:
  1690. +     vs->value.ivar = INT_VAR;
  1691. +     break;
  1692. +     
  1693. +      case V_KEY:
  1694. +     vs->value.key = KEY_VAR;
  1695. +     break;
  1696. +     
  1697. +      case V_SPECIAL:
  1698. +     msg("Cannot push pseudo variable %s", var->var_name);
  1699. +     break;
  1700. +     }
  1701. +     
  1702. +     return 1;
  1703. + }
  1704. +     
  1705. + restore_variables()
  1706. + {
  1707. +     register struct variable_defs *var;
  1708. +     register struct var_stack *vs, *vs1;
  1709. +     
  1710. +     vs = var_stack; 
  1711. +     while (vs != NULL) {
  1712. +     if ((var = vs->v) == NULL) {
  1713. +         var_stack = vs->next;
  1714. +         vs->next = vs_pool;
  1715. +         vs_pool = vs;
  1716. +         return;
  1717. +     }
  1718. +     
  1719. +     switch (VAR_TYPE) {
  1720. +         
  1721. +      case V_STRING:
  1722. +         switch (var->var_op) {
  1723. +          case 0:    /* only restore the string if changed; then we    */
  1724. +          case 2:    /* can also free the memory occupied by the    */
  1725. +          case 3:    /* 'new' value (if not NULL)            */
  1726. +         if (STR_VAR != vs->value.str) {
  1727. +             if (STR_VAR != NULL) free(STR_VAR);
  1728. +             STR_VAR = vs->value.str;
  1729. +         }
  1730. +         break;
  1731. +         
  1732. +          case 1:    /* it fitted before, so it will fit againg */
  1733. +         strcpy(CBUF_VAR, vs->value.str);
  1734. +         free(vs->value.str);
  1735. +         break;
  1736. +         }
  1737. +         break;
  1738. +         
  1739. +      case V_BOOLEAN:
  1740. +         BOOL_VAR = vs->value.bool;
  1741. +         break;
  1742. +         
  1743. +      case V_INTEGER:
  1744. +         INT_VAR = vs->value.ivar;
  1745. +         break;
  1746. +         
  1747. +      case V_KEY:
  1748. +         KEY_VAR = vs->value.key;
  1749. +         break;
  1750. +         
  1751. +      case V_SPECIAL:    /* these are not saved, so... */
  1752. +         break;
  1753. +     }
  1754. +     vs1 = vs->next;
  1755. +     vs->next = vs_pool;
  1756. +     vs_pool = vs;
  1757. +     vs = vs1;
  1758. +     }
  1759. +     var_stack = NULL;
  1760. + }
  1761. + static var_on_stack(var)
  1762. + register struct variable_defs *var;
  1763. + {
  1764. +     register struct var_stack *vs;
  1765. +     for (vs = var_stack; vs; vs = vs->next)
  1766. +     if (vs->v == var) return 1;
  1767. +     return 0;
  1768. + }
  1769.  
  1770.